import org.web3j.protocol.Web3j;
import org.web3j.protocol.admin.Admin;
import org.web3j.protocol.admin.methods.response.BooleanResponse;
import org.web3j.protocol.admin.methods.response.NewAccountIdentifier;
import org.web3j.protocol.admin.methods.response.PersonalUnlockAccount;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.DefaultBlockParameterNumber;
import org.web3j.protocol.core.Request;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.*;
import org.web3j.protocol.geth.Geth;
import org.web3j.protocol.http.HttpService;
import org.web3j.utils.Convert;

import java.io.IOException;
import java.math.BigInteger;

public class EthServicetest {
	private static String URL = "http://10.12.8.227:8545";
	private static HttpService httpService;

	/**
	 *   初始化web3j普通api调用     
	 * 
	 * @return web3j      
	 */
	public static Web3j initWeb3j() {
		return Web3j.build(getService());
	}

	/**
	 *   初始化personal级别的操作对象      
	 *   @return Geth      
	 */
	public Geth initGeth() {
		return Geth.build(getService());
	}

	/**
	 * 初始化admin级别操作的对象
	 * 
	 * @return Admin
	 */

	public static Admin initAdmin() {
		return Admin.build(getService());
	}

	/**
	 * 通过http连接到geth节点    
	 * 
	 * @return httpService
	 */
	private static HttpService getService() {
		if (httpService == null) {
			httpService = new HttpService(URL);
		}
		return httpService;
	}

	/**
	 *   输入密码创建地址            
	 *   @param password 密码（建议同一个平台的地址使用一个相同的，且复杂度较高的密码）
	 *   @return 地址hash      
	 *   @throws IOException      
	 */
	public String newAccount(String password) throws IOException {
		Admin admin = initAdmin();
		Request<?, NewAccountIdentifier> request = admin.personalNewAccount(password);
		NewAccountIdentifier result = request.send();
		return result.getAccountId();
	}

	/**
	 *   获得当前区块高度
	 *   @return 当前区块高度
	 *   @throws IOException      
	 */
	public BigInteger getCurrentBlockNumber() throws IOException {
		Web3j web3j = initWeb3j();
		Request<?, EthBlockNumber> request = web3j.ethBlockNumber();
		return request.send().getBlockNumber();
	}

	/**
	 *   解锁账户，发送交易前需要对账户进行解锁
	 *   @param address  地址
	 *   @param password 密码
	 *   @param duration 解锁有效时间，单位秒
	 *   @return
	 *   @throws IOException
	 */
	public Boolean unlockAccount(String address, String password, BigInteger duration) throws IOException {
		Admin admin = initAdmin();
		Request<?, PersonalUnlockAccount> request = admin.personalUnlockAccount(address, password, duration);
		PersonalUnlockAccount account = request.send();
		return account.accountUnlocked();
	}
	
	/**
     * 账户解锁，使用完成之后需要锁定
     *
     * @param address
     * @return
     * @throws IOException
     */
	public Boolean lockAccount(String address) throws IOException {
		Geth geth = initGeth();
		Request<?, BooleanResponse> request = geth.personalLockAccount(address);
		BooleanResponse response = request.send();
		return response.success();
	}

	/**
     * 根据hash值获取交易
     *
     * @param hash
     * @return
     * @throws IOException
     */
	public EthTransaction getTransactionByHash(String hash) throws IOException {
		Web3j web3j = initWeb3j();
		Request<?, EthTransaction> request = web3j.ethGetTransactionByHash(hash);
		EthTransaction send = request.send();
		return send;
	}

	/**
     * 获得ethblock
     *
     * @param blockNumber 根据区块编号
     * @return
     * @throws IOException
     */
	public EthBlock getBlockEthBlock(Integer blockNumber) throws IOException {
		Web3j web3j = initWeb3j();
		DefaultBlockParameter defaultBlockParameter = new DefaultBlockParameterNumber(blockNumber);
		Request<?, EthBlock> request = web3j.ethGetBlockByNumber(defaultBlockParameter, true);
		EthBlock ethBlock = request.send();
		return ethBlock;
	}

		/**
	     * 发送交易并获得交易hash值
	     *
	     * @param transaction
	     * @param password
	     * @return
	     * @throws IOException
	     */
	public static String sendTransaction(Transaction transaction, String password) throws IOException {
		Admin admin = initAdmin();
		Request<?, EthSendTransaction> request = admin.personalSendTransaction(transaction, password);
		EthSendTransaction ethSendTransaction = request.send();
		return ethSendTransaction.getTransactionHash();
	}

		/**
	     * 指定地址发送交易所需nonce获取
	     *
	     * @param address 待发送交易地址
	     * @return
	     * @throws IOException
	     */
	public BigInteger getNonce(String address) throws IOException {
		Web3j web3j = initWeb3j();
		Request<?, EthGetTransactionCount> request = web3j.ethGetTransactionCount(address,
				DefaultBlockParameterName.LATEST);
		return request.send().getTransactionCount();
	}

	/**
	 * 查询账户余额
	 * @param address 账户地址
	 */
	public BigInteger getBalance(String address) throws IOException {
		Web3j web3j = initWeb3j();
		Request<?, EthGetBalance> ethGetBalance = web3j.ethGetBalance(address, DefaultBlockParameterName.LATEST);
		return ethGetBalance.send().getBalance();
	}
	
	/**
	 * 开始挖矿
	 * 
	 */
	public void miner() throws IOException {
		Geth initGeth = initGeth();
		Request<?, MinerStartResponse> minerStart = initGeth.minerStart(1);
		MinerStartResponse send = minerStart.send();
	}
	
	/**
	 * 停止挖矿
	 * s
	 */
	public boolean stopMiner() throws IOException {
		Geth initGeth = initGeth();
		Request<?, BooleanResponse> minerStop = initGeth.minerStop();
		BooleanResponse send = minerStop.send();
		Boolean result = send.getResult();
		return result;
	}
	
	
	public static void main(String[] args) throws IOException {
		String url = "http://10.12.8.227:8545";
		//Geth geth = Geth.build(new HttpService(url));
		Admin geth = Admin.build(new HttpService(url));
		
		BigInteger nonce = null;//new BigInteger("2");
		BigInteger gasPrice = new BigInteger("10000000000000");
		BigInteger gasLimit = new BigInteger("30400");
		
		// GAS价格  
		BigInteger GAS_PRICE = null;//BigInteger.valueOf(20_000_000_000L);
		// GAS上限  
		BigInteger GAS_LIMIT = null;//BigInteger.valueOf(4_300_000L);
		
		
		
		BigInteger value = Convert.toWei("12", Convert.Unit.ETHER).toBigInteger();
		
		//System.out.println(new BigInteger("15", 10).toString(16));0x7f9e28a421ad5dd04a52326e4e5863d41a577010
		Transaction transaction = Transaction.createEtherTransaction("0x7f9e28a421ad5dd04a52326e4e5863d41a577010", nonce, GAS_PRICE, GAS_LIMIT, "0x1e5f0d70417defa2d5d41b7dc6c8f594e377454f", value);
		
		Request<?, EthSendTransaction> ethSendTransaction = geth.ethSendTransaction(transaction);
		
		Request<?, EthSendTransaction> personalSendTransaction = geth.personalSendTransaction(transaction, "654321");
		
		EthSendTransaction ethSend = ethSendTransaction.send();
		EthSendTransaction personalSend = personalSendTransaction.send();
		String transactionHash = ethSend.getTransactionHash();
		String transactionHash2 = personalSend.getTransactionHash();
		System.out.println(transactionHash + "-----" + transactionHash2);
		
	}
	
}
